#!/usr/bin/python3
# -*- coding: utf-8 -*-

import click
import logging
import os
import re
import socket
from dotenv import load_dotenv
from shutil import copyfile
from urllib.parse import urlparse

logging.basicConfig(level=logging.INFO,
                    format='%(thread)d %(levelname)s %(asctime)s [%(filename)s:%(lineno)d] %(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    )
logger = logging.getLogger('simple')


def validate_url(ctx, param, value):
    if (value.startswith("http://") is True or value.startswith("https://") is True) and value.endswith("/") is False:
        return value
    raise click.BadParameter('域名输入不合规,请验证后重试')


def validate_qq(ctx, param, value):
    if len(value) >= 1:
        if value.isDigit():
            pass
        else:
            raise click.BadParameter("输入的QQ号不正确")
    return value


def check_port_in_use(port, host='127.0.0.1'):
    s = None
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.settimeout(1)
        s.connect((host, int(port)))
        return True
    except socket.error:
        return False
    finally:
        if s:
            s.close()


# 获取可用端口
def getAllowPort(start=5500):
    startPort = start
    while 1:
        if check_port_in_use(startPort):
            logger.error("端口%s被占用,将变更为%d", startPort, startPort + 1)
            startPort += 1
        else:
            break
    return startPort


# 变更当前目录为域名
def changePwdIsDomain(domain):
    d = urlparse(domain)
    cwd = os.getcwd()
    parent, name = os.path.split(cwd)
    new_name = os.path.join(parent, d.hostname)
    os.rename(cwd, new_name)


# 解析出环境变量名
def parseToEnvName(name):
    b = name.split("_")
    eName = []
    for i in b:
        eName.append(i[0].upper())
        eName.append(i[1:])
    # 环境变量的名字
    return "".join(eName)


# 配置文件覆盖
def configGen(*args, **kwargs):
    # 先备份之前的配置文件
    envPath = os.path.join(os.getcwd(), "env")
    baseEnvPath = os.path.join(envPath, "base.env")
    load_dotenv(dotenv_path=baseEnvPath, encoding="utf-8")
    # 备份文件名
    backPath = os.path.join(envPath, "base.env_back")
    if os.path.exists(backPath):
        os.remove(backPath)
    # 进行备份
    copyfile(baseEnvPath, backPath)
    # 读取配置文件
    with open(baseEnvPath, "r", encoding="utf-8") as f:
        envFile = f.readlines()
    # 进行文件内容替换
    for (k, v) in kwargs.items():
        # 环境变量的名字
        envName = parseToEnvName(k)
        for i, o in enumerate(envFile):
            if o.startswith(envName):
                line = "%s=%s\n" % (envName, v)
                envFile[i] = line
    # 写入文件
    with open(baseEnvPath, "w", encoding="utf-8") as f:
        for i in envFile:
            f.writelines(i)


# 端口变更
def portConfChange(port):
    fPath = os.path.join(os.getcwd(), "docker-compose.yml")
    with open(fPath, "r", encoding="utf-8") as f:
        fi = f.read()
    pattern = re.compile(r'apiPort:-(\d+)\}:')
    m = pattern.findall(fi)
    if len(m) >= 1:
        fi = fi.replace("${apiPort:-%s}" % m[0], "${apiPort:-%s}" % port)
        with open(fPath, 'w', encoding="utf-8") as f:
            f.write(fi)
    else:
        raise Exception("替换端口失败,获取端口信息错误")


# 从备份文件还原
def runReset():
    logger.info("正在进行env文件从备份还原")
    envPath = os.path.join(os.getcwd(), "env")
    baseEnvPath = os.path.join(envPath, "base.env")
    backPath = os.path.join(envPath, "base.env_back")
    # 先判断文件是否存在
    if os.path.exists(backPath) is False:
        raise Exception("备份文件不存在")
    # 先删除现在的文件
    os.remove(baseEnvPath)
    # 进行还原操作
    copyfile(backPath, baseEnvPath)
    logger.info("还原成功")


@click.group()
def cli():
    pass


@click.command()
def change_port():
    logger.info("检测可用端口中")
    allowPort = getAllowPort()
    logger.info("获取到%s端口可用", allowPort)
    portConfChange(allowPort)
    logger.info("端口设置变更完成")


if __name__ == '__main__':
    # runReset()
    # entry()
    cli.add_command(change_port)
    cli()
